/* -*- c++ -*-
*
* postlist.cpp
*
* Copyright (C) 2005 Petter Stokke <ummo@hellokitty.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include "postlist.h"

#include <kdebug.h>
#include <klocale.h>
#include <kglobal.h>
#include <kpopupmenu.h>
#include <kiconloader.h>
#include <kapplication.h>
#include <kurldrag.h>

#include <qclipboard.h>
#include <qmime.h>

// --- PostList ---

PostList::PostList( BookmarkAPI* api, QWidget* parent, const char* name )
        : KListView( parent, name )
        , QToolTip( viewport() )
        , m_api( api )
        , m_posts( 0 )
        , m_newWindowByDefault( false )
{
    addColumn( i18n( "Post" ) );
    setFullWidth( true );
    setAllColumnsShowFocus( true );
    KListView::setEnabled( false );
    setAcceptDrops( true );
    setDropVisualizer( false );

    connect( this, SIGNAL( contextMenu( KListView*, QListViewItem*, const QPoint& ) ),
             this, SLOT( slotContextMenu( KListView*, QListViewItem*, const QPoint& ) ) );
    connect( this, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int ) ),
             this, SLOT( slotOpenCurrentPostDefaultAction() ) );
    connect( this, SIGNAL( dropped( QDropEvent*, QListViewItem* ) ),
             this, SLOT( slotDropped( QDropEvent* ) ) );
}

PostListItem* PostList::currentPost() const
{
    return dynamic_cast<PostListItem*>( currentItem() );
}

QString PostList::tipText( Post* post )
{
    QString s = !m_tipThumb.isNull() ? QString( "<table><tr><td><img src=\"thumbshots/%1\"></td><td><table>" ).arg( m_tipThumb ) : "<table>";
    s += i18n( "<tr><td><b>Title:</b></td><td>%1</td></tr>" ).arg( post->title() );
    if ( post->description().length() )
        s += i18n( "<tr><td><b>Description:</b></td><td>%1</td></tr>" ).arg( post->description() );
    s += i18n( "<tr><td><b>URL:</b></td><td>%1</td></tr>" ).arg( post->url().prettyURL() );
    /* TODO: Fix this when global tags are reimplemented.
    if ( item->post()->user() != m_api->user() )
    s += i18n( "<tr><td><b>User:</b></td><td>%1</td></tr>" ).arg( item->post()->user() );
    */
    QString tags( i18n( "empty tag list", "(none)" ) );
    if ( post->tags().count() )
        tags = post->tags().join( " " );
    s += i18n( "<tr><td><b>Tags:</b></td><td>%1</td></tr>" ).arg( tags );
    s += !m_tipThumb.isNull() ? "</table></td></tr></table>" : "</table>";
    return s;
}

void PostList::maybeTip( const QPoint& p )
{
    PostListItem * item = dynamic_cast<PostListItem*>( itemAt( p ) );
    if ( !item )
        return ;

    QRect r( itemRect( item ) );
    if ( !r.isValid() )
        return ;

    m_tipFor = item->post();
    m_tipRect = r;
    KURL u, thumbshot( "http://open.thumbshots.org/image.pxf" );
    u.setProtocol( m_tipFor->url().protocol() );
    if ( u.protocol() == "https" )
        u.setProtocol( "http" );
    u.setHost( m_tipFor->url().host() );
    bool useTip = u.protocol() == "http";
    if ( useTip ) {
        thumbshot.addQueryItem( "url", u.url() );
        m_tipThumb = u.host();
        if ( !m_fetchedThumbs.contains( m_tipThumb ) ) {
            KIconLoader * icons = KGlobal::iconLoader();
            QPixmap px = icons->loadIcon( "html", KIcon::Desktop );
            QMimeSourceFactory::defaultFactory() ->setPixmap( QString( "thumbshots/" ) + m_tipThumb, px );
            KIO::StoredTransferJob* job = KIO::storedGet( thumbshot, true, false );
            connect( job, SIGNAL( result( KIO::Job* ) ), this, SLOT( slotThumbJobResult( KIO::Job* ) ) );
            job->setName( m_tipThumb.latin1() );
            m_fetchedThumbs.replace( m_tipThumb, true );
        }
    } else {
        m_tipThumb = QString::null;
    }

    tip( r, tipText( item->post() ) );
}

void PostList::slotThumbJobResult( KIO::Job* j )
{
    KIO::StoredTransferJob * job = dynamic_cast<KIO::StoredTransferJob*>( j );
    ASSERT( job );
    if ( !job->error() ) {
        QImage thumb( job->data() );
        QString tipThumb = QString::fromLatin1( job->name() );
        QMimeSourceFactory::defaultFactory() ->setImage( QString( "thumbshots/" ) + tipThumb, thumb );
        if ( m_tipThumb == tipThumb )
            tip( m_tipRect, tipText( m_tipFor ) );
    }
}

void PostList::setTagFilter( const QStringList& tags )
{
    m_searchFilter = QString::null;
    m_tagFilter = tags;
    if ( tags.count() ) {
        emit titleChanged( i18n( "<b>Tag: %1</b>" ).arg( tags.join( "+" ) ) );
        setPosts( m_posts->postsWithTags( tags ) );
        KListView::setEnabled( true );
    } else {
        emit titleChanged( i18n( "<b>Tag: %1</b>" ).arg( i18n( "empty tag list", "(none)" ) ) );
        KListView::clear();
        KListView::setEnabled( false );
    }
    tip( QRect(), QString::null );
}

void PostList::setSearchFilter( const QString& query )
{
    if ( m_searchFilter == query )
        return ;
    m_searchFilter = query;
    m_tagFilter = QStringList();
    if ( query.isEmpty() ) {
        emit titleChanged( i18n( "<b>Tag: %1</b>" ).arg( i18n( "empty tag list", "(none)" ) ) );
        KListView::clear();
        KListView::setEnabled( false );
    } else {
        emit titleChanged( i18n( "<b>Search: %1</b>" ).arg( query ) );
        setPosts( m_posts->postsMatchingQuery( query ) );
        KListView::setEnabled( true );
    }
    tip( QRect(), QString::null );
}

void PostList::setPosts( const QPtrList<Post>& p )
{
    KListView::clear();
    QPtrListIterator<Post> it( p );
    for ( ; it.current(); ++it )
        ( void ) new PostListItem( this, it.current() );
}

void PostList::updatePosts( Collection* c )
{
    m_posts = c;
    if ( tagFilter().count() )
        setTagFilter( tagFilter() );
    else if ( !searchFilter().isEmpty() )
        setSearchFilter( searchFilter() );
}

void PostList::slotContextMenu( KListView*, QListViewItem* i, const QPoint& pt )
{
    PostListItem * tag = dynamic_cast<PostListItem*>( i );
    if ( !tag )
        return ;

    KIconLoader* icons = KGlobal::iconLoader();
    KPopupMenu* pop = new KPopupMenu( this );
    pop->insertTitle( i18n( "Post" ) );
    pop->insertItem( icons->loadIconSet( "fileopen", KIcon::Small ), i18n( "&Open" ),
                     this, SLOT( slotOpenCurrentPost() ) );
    pop->insertItem( icons->loadIconSet( "fileopen", KIcon::Small ), i18n( "Open in New &Window" ),
                     this, SLOT( slotOpenCurrentPostInNewWindow() ) );
    pop->insertItem( icons->loadIconSet( "editcopy", KIcon::Small ), i18n( "Copy &Link Address" ),
                     this, SLOT( slotCopyURL() ) );
    pop->insertSeparator();
    /* FIXME: Enable this when global tags are reimplemented.
    if ( tag->post()->user() != m_api->user() )
        pop->insertItem( icons->loadIconSet( "bookmark_add", KIcon::Small ), i18n( "Post to &My Bookmarks" ),
                         this, SLOT( slotPostCurrentPost() ) );
    */
    pop->insertItem( icons->loadIconSet( "edit", KIcon::Small ), i18n( "&Edit Post" ),
                     this, SLOT( slotEditCurrentPost() ) );
    pop->insertSeparator();
    pop->setItemChecked( pop->insertItem( i18n( "Open &New Window on Double-Click" ), this, SLOT( slotToggleDefaultAction() ) ), m_newWindowByDefault );
    pop->popup( pt );
}

void PostList::slotToggleDefaultAction()
{
    m_newWindowByDefault = !m_newWindowByDefault;
    emit changedNewWindowByDefault( m_newWindowByDefault );
}

void PostList::slotOpenCurrentPostDefaultAction()
{
    PostListItem * post = currentPost();
    if ( post )
        emit openPostDefaultAction( post->post() );
}

void PostList::slotOpenCurrentPost()
{
    PostListItem * post = currentPost();
    if ( post )
        emit openPost( post->post() );
}

void PostList::slotOpenCurrentPostInNewWindow()
{
    PostListItem * post = currentPost();
    if ( post )
        emit openPostInNewWindow( post->post() );
}

void PostList::slotCopyURL()
{
    PostListItem * post = currentPost();
    if ( post ) {
        QClipboard * clip = KApplication::clipboard();
        clip->setText( post->post() ->url().url(), QClipboard::Selection );
        clip->setText( post->post() ->url().url(), QClipboard::Clipboard );
    }
}

void PostList::slotPostCurrentPost()
{
    PostListItem * post = currentPost();
    if ( post )
        emit submitURL( post->post() ->url(), post->post() ->tags() );
}

void PostList::slotEditCurrentPost()
{
    PostListItem * post = currentPost();
    if ( post )
        emit editPost( post->post() );
}

bool PostList::acceptDrag( QDropEvent* event ) const
{
    KURL::List uri;
    return KURLDrag::decode( event, uri );
}

void PostList::slotDropped( QDropEvent* event )
{
    KURL::List uri;
    if ( KURLDrag::decode( event, uri ) ) {
        QValueListConstIterator<KURL> it;
        for ( it = uri.begin(); it != uri.end(); ++it )
            emit urlDropped( ( *it ).url(), m_tagFilter );
    }
}



// --- PostListItem ---

PostListItem::PostListItem( PostList* parent, Post* post )
        : KListViewItem( parent )
        , m_post( post )
{
    updateFavicon();
}

Post* PostListItem::post() const
{
    return m_post;
}

void PostListItem::setPost( Post* post )
{
    m_post = post;
    updateFavicon();
    repaint();
}

QString PostListItem::text( int column ) const
{
    switch ( column ) {
    case 0:
        return m_post->title();
    default:
        return QString::null;
    }
}

void PostListItem::updateFavicon()
{
    QPixmap * icon = m_post->collection() ->api() ->faviconForURL( m_post->url() );
    if ( icon )
        m_favicon = *icon;
    else {
        KIconLoader * icons = KGlobal::iconLoader();
        m_favicon = icons->loadIcon( "html", KIcon::Small );
    }
}

const QPixmap* PostListItem::pixmap( int column ) const
{
    switch ( column ) {
    case 0:
        return & m_favicon;
    default:
        return 0;
    }
}

#include "postlist.moc"
